﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using HtmlAgilityPack;
using CoursePack;

namespace MyConcordiaAPI
{
    public delegate void RequestStatus(object sender, EventArgs e);

    public class CourseManipulation
    {
        #region Data
        private Course m_Course;
        public event RequestStatus OnRequestStatusChanged;
        string m_NetName;
        string m_Password;
        #endregion

        public CourseManipulation(Course _Course,string _NetName, string _Password)
        {
            this.m_Course = _Course;
            this.m_NetName = _NetName;
            this.m_Password = _Password;

        }

        public void AddCourse()
        {
            // First request, we login to MyConcordia Portal
            HttpRequest MyConcordiaLogin = new HttpRequest(HttpMethod.POST, new Uri("https://my.concordia.ca/psp/portprod/?cmd=login&languageCd=ENG"),
                "https://www.myconcordia.ca/",
                "my.concordia.ca",
                new CookieContainer());

            OnRequestStatusChanged("Connecting to MyConcordia Portal",new EventArgs());



            MyConcordiaLogin.SendRequest("userid=" + m_NetName + "&pwd=" + this.m_Password + "&GO=Sign+in&httpPort=&timezoneOffset=300&portal_pwd=" + m_Password);


            //Second request, we start a get a token to start the Registration session
            HttpRequest RegistrationPage = new HttpRequest(HttpMethod.GET, new Uri(" https://my.concordia.ca/psc/portprod/EMPLOYEE/EMPL/s/WEBLIB_CONCORD.CU_SIS_INFO.FieldFormula.IScript_WebReg1?PORTALPARAM_PTCNAV=CU_WEBREG1&EOPP.SCNode=EMPL&EOPP.SCPortal=EMPLOYEE&EOPP.SCName=CU_REGISTRATION&EOPP.SCLabel=Registration&EOPP.SCPTfname=CU_REGISTRATION&FolderPath=PORTAL_ROOT_OBJECT.CU_REGISTRATION.CU_WEBREG1&IsFolder=false&PortalActualURL=https%3a%2f%2fmy.concordia.ca%2fpsc%2fportprod%2fEMPLOYEE%2fEMPL%2fs%2fWEBLIB_CONCORD.CU_SIS_INFO.FieldFormula.IScript_WebReg1&PortalContentURL=https%3a%2f%2fmy.concordia.ca%2fpsc%2fportprod%2fEMPLOYEE%2fEMPL%2fs%2fWEBLIB_CONCORD.CU_SIS_INFO.FieldFormula.IScript_WebReg1&PortalContentProvider=EMPL&PortalCRefLabel=Undergraduate%20Registration&PortalRegistryName=EMPLOYEE&PortalServletURI=https%3a%2f%2fmy.concordia.ca%2fpsp%2fportprod%2f&PortalURI=https%3a%2f%2fmy.concordia.ca%2fpsc%2fportprod%2f&PortalHostNode=EMPL&NoCrumbs=yes"),
                 "https://my.concordia.ca/psp/portprod/EMPLOYEE/EMPL/s/WEBLIB_CONCORD.CU_SIS_INFO.FieldFormula.IScript_WebReg1?PORTALPARAM_PTCNAV=CU_WEBREG1&EOPP.SCNode=EMPL&EOPP.SCPortal=EMPLOYEE&EOPP.SCName=CU_REGISTRATION&EOPP.SCLabel=Registration&EOPP.SCPTfname=CU_REGISTRATION&FolderPath=PORTAL_ROOT_OBJECT.CU_REGISTRATION.CU_WEBREG1&IsFolder=false",
                 "my.concordia.ca",
                 MyConcordiaLogin.Cookies);
            OnRequestStatusChanged("Openning registration session...", new EventArgs());

            
            HttpWebResponse RegistrationPageResponse = RegistrationPage.SendRequest();



            // Third request, we start the real session registration page
            HttpRequest RegistrationSessionStart = new HttpRequest(HttpMethod.GET, new Uri("https://regsis.concordia.ca/portalRegora/undergraduate/wr150.asp" + RegistrationPageResponse.ResponseUri.Query),
                "https://my.concordia.ca/psp/portprod/EMPLOYEE/EMPL/s/WEBLIB_CONCORD.CU_SIS_INFO.FieldFormula.IScript_WebReg1?FolderPath=PORTAL_ROOT_OBJECT.CU_REGISTRATION.CU_WEBREG1&IsFolder=false&IgnoreParamTempl=FolderPath%2cIsFolder",
                "regsis.concordia.ca",
                RegistrationPage.Cookies);


            RegistrationSessionStart.SendRequest();
            string id = this.ExtractId(RegistrationSessionStart.ResponseStream);


            // Fourth request, we go to the record page
            HttpRequest RecordPage = new HttpRequest(HttpMethod.POST, new Uri("https://regsis.concordia.ca/portalRegora/undergraduate/wr200.asp"),
                "https://regsis.concordia.ca/portalRegora/undergraduate/wr150.asp" + RegistrationSessionStart.ResponseQuery,
                "regsis.concordia.ca",
                RegistrationSessionStart.Cookies);


            RecordPage.SendRequest(id);
            string id2 = this.ExtractId2(RecordPage.ResponseStream);




            // Fifth request, we add one class
            HttpRequest AddCoursePage = new HttpRequest(HttpMethod.POST, new Uri("https://regsis.concordia.ca/portalRegora/undergraduate/wr215.asp"),
                "https://regsis.concordia.ca/portalRegora/undergraduate/wr200.asp",
                "regsis.concordia.ca",
                RecordPage.Cookies);
            OnRequestStatusChanged("Adding the specified course to your list ...", new EventArgs());

            AddCoursePage.SendRequest("Id=" + id2 + "&language=1");



            // Sixth request, we add one class
            HttpRequest Gabadou = new HttpRequest(HttpMethod.POST, new Uri("https://regsis.concordia.ca/portalRegora/undergraduate/wr220.asp"),
                "https://regsis.concordia.ca/portalRegora/undergraduate/wr215.asp",
                "regsis.concordia.ca",
                AddCoursePage.Cookies);
            string data = "InputCourName=" + this.m_Course.CourseName + "&InputCourNum=" + this.m_Course.CourseNumber + "&InputCourSes=" + this.m_Course.Session + "&InputCourSec=&coursub=Submit&selectoption=S&Id=" + id2 + "&language=1";

            Gabadou.SendRequest(data);


            string title = System.Net.WebUtility.UrlEncode(this.ExtractCourseTitle(Gabadou.ResponseStream));



            // Sixth request, we add one class
            HttpRequest Confirmation = new HttpRequest(HttpMethod.POST, new Uri("https://regsis.concordia.ca/portalRegora/undergraduate/wr225.asp"),
                "https://regsis.concordia.ca/portalRegora/undergraduate/wr220.asp",
                "regsis.concordia.ca",
                Gabadou.Cookies);

            string RelSec1, RelSec2, CatNum, Days;

            RelSec1 = (this.m_Course.HasTutorial) ? this.m_Course.Tutorial.Section : "++";
            RelSec2 = (this.m_Course.HasLab) ? this.m_Course.Lab.Section : "++";
            CatNum = "12345";

            if (this.m_Course.HasTutorial && this.m_Course.HasLab)
                Days = m_Course.DaysLab;

            else if (this.m_Course.HasLab && !this.m_Course.HasTutorial)
                Days = m_Course.DaysLab;

            else if (this.m_Course.HasTutorial)
                Days = m_Course.DaysTutorial;
            else
                Days = m_Course.DaysLecture;



            if (this.m_Course.HasLab)
            {
                data = "CourName=" + this.m_Course.CourseName
                    + "&CourNo=" + this.m_Course.CourseNumber
                    + "+&Sess=" + this.m_Course.Session
                    + "&MainSec=" + this.m_Course.Lecture.Section
                    + "&RelSec1=" + RelSec1
                    + "&RelSec2=" + RelSec2
                    + "&CatNum=" + CatNum
                    + "&Start=" + this.m_Course.Tutorial.StartTime
                    + "&Finish=" + this.m_Course.Tutorial.EndTime
                    + "&Days=" + Days
                    + "&Campus=" + this.m_Course.Campus
                    + "&Title=" + this.m_Course.CourseTitle
                    + "&Id=" + id2 + "&language=1";
            }
            else if (this.m_Course.HasTutorial)
            {
                data = "CourName=" + this.m_Course.CourseName
                    + "&CourNo=" + this.m_Course.CourseNumber
                    + "+&Sess=" + this.m_Course.Session
                    + "&MainSec=" + this.m_Course.Lecture.Section
                    + "&RelSec1=" + RelSec1
                    + "&RelSec2=" + RelSec2
                    + "&CatNum=" + CatNum
                    + "&Start=" + this.m_Course.Lab.StartTime
                    + "&Finish=" + this.m_Course.Lab.EndTime
                    + "&Days=" + Days
                    + "&Campus=" + this.m_Course.Campus
                    + "&Title=" + this.m_Course.CourseTitle
                    + "&Id=" + id2 + "&language=1";
            }

            Confirmation.SendRequest(data);

            // Seventh request, we add one class
            HttpRequest AddCourseForReal = new HttpRequest(HttpMethod.POST, new Uri("https://regsis.concordia.ca/portalRegora/undergraduate/wr300.asp"),
                "https://regsis.concordia.ca/portalRegora/undergraduate/wr225.asp",
                "regsis.concordia.ca",
                Confirmation.Cookies);
            string lol = "cournam=" + this.m_Course.CourseName
                + "&courno=" + this.m_Course.CourseNumber
                + "+&acyear=2013&session=" +this.m_Course.Session
                + "&mainsec=" + this.m_Course.Lecture.Section
                + "&RelSec1=" + RelSec1
                + "&RelSec2=" + RelSec2
                + "&subses=++&catalog=12345"         
                + "&Id=" + id2
                + "&language=1";

            OnRequestStatusChanged("Confirming your course request", new EventArgs());


            AddCourseForReal.SendRequest(lol);

            bool error = false;
            string errorTxt = "";
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.OptionFixNestedTags = true;

            htmlDoc.LoadHtml(AddCourseForReal.ResponseStream);

            foreach (HtmlNode input in htmlDoc.DocumentNode.SelectNodes("//font"))
            {

                if (input.InnerHtml.Contains("Reason:"))
                {
                    error = true;
                    errorTxt = input.InnerHtml;
                    break;
                }
            }

            if (error)
            {
                OnRequestStatusChanged("Course Registration Denied", new EventArgs());
            }
            else
            {
                OnRequestStatusChanged("Course Registration Succeeded", new EventArgs());
            }
        }

        #region Private Methods
        private string ExtractCourseTitle(string _Document)
        {
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.OptionFixNestedTags = true;

            htmlDoc.LoadHtml(_Document);
            foreach (HtmlNode input in htmlDoc.DocumentNode.SelectNodes("//input"))
            {

                if (input.Attributes[1].Value == "Title")
                    return input.Attributes[2].Value;


            }
            return null;
        }

        private string ExtractId(string _Document)
        {
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.OptionFixNestedTags = true;

            htmlDoc.LoadHtml(_Document);
            HtmlNode secondForm = htmlDoc.GetElementbyId("form2");
            HtmlNode id = secondForm.NextSibling.NextSibling;
            HtmlNode currYear = id.NextSibling.NextSibling;
            HtmlNode currSess = currYear.NextSibling.NextSibling;

            string strid = id.Attributes[2].Value;
            string strcurrYear = currYear.Attributes[2].Value;
            string strcurrSess = currSess.Attributes[2].Value;

            return "Id=" + strid + "&CurrYear=" + strcurrYear + "&CurrSess=" + strcurrSess + "&language=1&Continue=Continue";
        }

        private string ExtractId2(string _Document)
        {
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.OptionFixNestedTags = true;

            htmlDoc.LoadHtml(_Document);
            HtmlNode secondForm = htmlDoc.GetElementbyId("form2");
            HtmlNode id = secondForm.NextSibling.NextSibling;

            string strid = id.Attributes[2].Value;

            return strid;
        }

        private string ExtractId3(string _Document)
        {
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.OptionFixNestedTags = true;

            htmlDoc.LoadHtml(_Document);
            HtmlNode secondForm = htmlDoc.GetElementbyId("form3");
            HtmlNode id = secondForm.NextSibling.NextSibling;

            string strid = id.Attributes[2].Value;

            return strid;
        }
        #endregion
    }
}
